package cn.virens.config;

import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import cn.virens.web.components.shiro.CustomAuthorizingRealm;
import cn.virens.web.components.shiro.CustomFormAuthenticationFilter;
import cn.virens.web.components.shiro.CustomLogoutFilter;
import cn.virens.web.components.shiro.CustomShiroFilterFactoryBean;
import cn.virens.web.components.shiro.CustomUserFilter;
import cn.virens.web.components.shiro.cookie.RememberMeCookie;
import cn.virens.web.components.shiro.spring.SpringCacheManage;

/**
 * 权限框架配置
 * 
 * @作者 : loioi
 * @创建时间 :2017年8月1日 下午1:37:08
 */
@Configuration
public class SpringShiroSourceConfig {

	/**
	 * Shiro 缓存管理器配置
	 * 
	 * @param cacheManager
	 * @return
	 */
	@Bean("shiro-cachemanager")
	public SpringCacheManage springCacheManage(org.springframework.cache.CacheManager cacheManager) {
		return new SpringCacheManage(cacheManager);
	}

	/**
	 * Realm实现
	 * 
	 * @return
	 */
	@Bean("shiro-realm")
	public CustomAuthorizingRealm authorizingRealm() {
		CustomAuthorizingRealm realm = new CustomAuthorizingRealm();
		realm.setAuthorizationCachingEnabled(true);
		realm.setAuthenticationCachingEnabled(true);
		realm.setAuthorizationCacheName("shiro-authorizationCache");
		realm.setAuthenticationCacheName("shiro-authenticationCache");

		return realm;
	}

	/**
	 * rememberMe管理器
	 * 
	 * @return
	 */
	@Bean("shiro-remembermemanager")
	public CookieRememberMeManager rememberMeManager() {
		CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
		rememberMeManager.setCookie(new RememberMeCookie());
		rememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));

		return rememberMeManager;
	}

	/**
	 * 会话管理器
	 * 
	 * @param sessionDAO
	 * @return
	 */
	@Bean("shiro-sessionmanager")
	public ServletContainerSessionManager sessionManager() {
		return new ServletContainerSessionManager();
	}

	/**
	 * 安全管理器
	 * 
	 * @return
	 */
	@Bean("shiro-securitymanager")
	public DefaultWebSecurityManager securityManager(//
			@Qualifier("shiro-realm") Realm realm, //
			@Qualifier("shiro-cachemanager") SpringCacheManage cacheManager, //
			@Qualifier("shiro-sessionmanager") SessionManager sessionManager, //
			@Qualifier("shiro-remembermemanager") RememberMeManager rememberMeManager) {

		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

		securityManager.setRealm(realm);
		securityManager.setCacheManager(cacheManager);
		securityManager.setSessionManager(sessionManager);
		securityManager.setRememberMeManager(rememberMeManager);

		return securityManager;
	}

	/**
	 * Shiro的Web过滤器
	 * 
	 * @return
	 * @throws Exception
	 */
	@Bean("shiroFilter")
	public ShiroFilterFactoryBean shiroFilter(@Qualifier("shiro-securitymanager") SecurityManager securityManager) throws Exception {
		CustomShiroFilterFactoryBean factoryBean = new CustomShiroFilterFactoryBean();
		factoryBean.setSecurityManager(securityManager);
		factoryBean.setLoginUrl("/admin/login.jspx");
		factoryBean.setSuccessUrl("/admin/index.jspx");
		factoryBean.setUnauthorizedUrl("/error/403");

		factoryBean.addFilter("user", new CustomUserFilter());
		factoryBean.addFilter("logout", new CustomLogoutFilter());
		factoryBean.addFilter("authc", new CustomFormAuthenticationFilter());

		factoryBean.addFilterChain("/admin/logout.jspx", "logout");
		factoryBean.addFilterChain("/admin/login.jspx", "authc");
		factoryBean.addFilterChain("/admin/**", "user");
		factoryBean.addFilterChain("/**", "anon");

		return factoryBean;
	}

	/**
	 * 授权 注解配置
	 * 
	 * @return
	 */
	@Bean
	public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
		return new DefaultAdvisorAutoProxyCreator();
	}

	/**
	 * 授权 注解配置
	 * 
	 * @return
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor attributeSourceAdvisor(@Qualifier("shiro-securitymanager") SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor attributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		attributeSourceAdvisor.setSecurityManager(securityManager);

		return attributeSourceAdvisor;
	}
}